package com.bgc.codegenerate.utils;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.net.URL;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件生成器
 */
@Slf4j
public class FileGenerator {

    private static String sf = "%s/%s/%s%s";

    public static void writeFile(GenerateConfiguration configuration, List<TableColumn> columns)
            throws IOException, TemplateException {
        log.info("开始生成文件!");
        // 测试环境获取项目根目录路径
        URL resource = CodeGeneratorUtil.class.getResource("/ftl");
        String path = resource.getPath();
		path = URLDecoder.decode(path, "UTF-8");

        // Jar包获取根目录路径
//        File r = new File("");
//        String path = r.getAbsolutePath();
//        System.out.println("path:" + path);
        Configuration cfg = new Configuration();
        cfg.setDirectoryForTemplateLoading(new File(path)); // 需要文件夹绝对路径
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        Map root = new HashMap();
        root.put("configuration", configuration);
        root.put("columnList", columns);
        writeSingleFile(cfg, root, "PO.ftl", configuration.getProjectPath(),
                configuration.getJavaModelPackage().replace(".", "/") + "/entity",
                configuration.getDomainObjectName(), ".java", configuration.getOverwrite());
        // writeSingleFile(cfg, root, "VO.ftl", configuration.getProjectPath(),
        // configuration.getJavaModelPackage().replace(".", "/") + "/vo",
        // configuration.getDomainObjectName(), "VO.java",
        // configuration.getOverwrite());
        // writeSingleFile(cfg, root, "DTO.ftl", configuration.getProjectPath(),
        // configuration.getJavaModelPackage().replace(".", "/") + "/dto",
        // configuration.getDomainObjectName(), "DTO.java",
        // configuration.getOverwrite());
        writeSingleFile(cfg, root, "ServiceImpl.ftl", configuration.getProjectPath(),
                configuration.getJavaModelPackage().replace(".", "/") + "/service/impl",
                configuration.getDomainObjectName(), "ServiceImpl.java", configuration.getOverwrite());
//		writeSingleFile(cfg, root, "Service.ftl", configuration.getProjectPath(),
//		                configuration.getJavaModelPackage().replace(".", "/") + "/service",
//		                configuration.getDomainObjectName(), "Service.java", configuration.getOverwrite());
        writeSingleFile(cfg, root, "Controller.ftl", configuration.getProjectPath(),
                configuration.getJavaModelPackage().replace(".", "/") + "/controller",
                configuration.getDomainObjectName(), "Controller.java", configuration.getOverwrite());
        writeSingleFile(cfg, root, "Mapper.ftl", configuration.getProjectPath(),
                configuration.getJavaModelPackage().replace(".", "/") + "/dao",
                configuration.getDomainObjectName(), "Mapper.java", configuration.getOverwrite());
        writeSingleFile(cfg, root, "Mapper_xml.ftl", configuration.getProjectPath(),
                configuration.getJavaModelPackage().replace(".", "/") + "/mapper",
                configuration.getDomainObjectName(), "Mapper.xml", configuration.getOverwrite());
    }

    public static boolean writeSingleFile(Configuration cfg, Map root, String template, String projectPath,
                                          String packagePath, String fileName, String suffix, Boolean overwrite)
            throws IOException, TemplateException {
        Template temp = cfg.getTemplate(template);
        File file = new File(String.format(sf, projectPath, packagePath, fileName, suffix));
        if (!file.getParentFile().exists()) {
            if (!file.getParentFile().mkdirs()) {
                log.info("创建目标文件所在目录失败！");
                return false;
            }
        }
        if (file.exists()) {
            if (!overwrite) {
                log.info(String.format("创建单个文件%s失败! 文件已存在", file.getPath()));
                return false;
            }
        } else {
            if (file.createNewFile()) {
                log.info(String.format("创建单个文件%s成功!", file.getPath()));
            } else {
                log.info(String.format("创建单个文件%s失败!", file.getPath()));
                return false;
            }
        }
        Writer out = null;
        try {
            out = new FileWriter(file);
            temp.process(root, out);
            out.flush();
            log.info(String.format(sf + "完成.", projectPath, packagePath, fileName, suffix));
        } catch (Exception e) {
            log.info(String.format("写入%s失败!", file.getPath()));
        } finally {
            if (out != null) {
                out.close();
            }
        }
        return true;
    }
}
